#pragma once

#include <iostream>
#include <sys/epoll.h>
#include <memory>
#include <unordered_map>

#include "Epoller.hpp"
#include "Listener.hpp"
#include "Connection.hpp"

class TcpServer
{
    static const int revs_num = 1024; // 最大事件数
private:
    // 判断_connections是否存在sockfd
    bool IsConnectionExistHelper(int sockfd)
    {
        auto iter = _connections.find(sockfd);
        if (iter == _connections.end())
            return false;
        else
            return true;
    }

    // 判断connection是否已经注册
    bool IsConnectionExist(const std::shared_ptr<Connection> &conn)
    {
        return IsConnectionExistHelper(conn->GetFd());
    }

    // 判断sockfd是否已经注册
    bool IsConnectionExist(int sockfd)
    {
        return IsConnectionExistHelper(sockfd);
    }

    // 判断_connections是否为空
    bool IsConnectionsEmpty()
    {
        return _connections.empty();
    }

    //
    int LoopOnce(int timeout)
    {                                                              // 超时时间
        return _epoller_ptr->WaitEvents(_revs, revs_num, timeout); // 等待事件
    }

    // 事件分派
    void Dispatcher(int num)
    {
        // 分拣事件
        for (int i = 0; i < num; i++)
        {
            int sockfd = _revs[i].data.fd;     // 获取描述符
            uint32_t events = _revs[i].events; // 获取事件

            // 处理ERR事件
            if (events & EPOLLERR)
                events |= EPOLLIN | EPOLLOUT; // 转化为读写事件
            // 处理HUP事件
            if (events & EPOLLHUP)
                events |= EPOLLIN | EPOLLOUT; // 转化为读写事件

            // 处理读事件
            if (events & EPOLLIN)
            {
                // 判断_connections是否存在sockfd
                if (IsConnectionExist(sockfd))
                    _connections[sockfd]->Recver();
            }

            // 处理写事件
            if (events & EPOLLOUT)
            {
                // 判断_connections是否存在sockfd
                if (IsConnectionExist(sockfd))
                    _connections[sockfd]->Sender();
            }
        }
    }

public:
    TcpServer() : _epoller_ptr(std::make_unique<Epoller>()),
                  _isrunning(false)
    {
    }

    // 启动服务器
    void Start()
    {
        // 判断_connecions是否为空
        if (IsConnectionsEmpty())
        {
            return;
        }

        int timeout = -1; // 超时时间
        _isrunning = true;
        while (1)
        {
            int n = LoopOnce(timeout); // 获取就绪事件
            Dispatcher(n);             // 事件派发
        }
        _isrunning = false;
    }

    // 增加connection
    void AddConnection(std::shared_ptr<Connection> &conn)
    {
        // 检测conn是否已经注册
        if (IsConnectionExist(conn))
        {
            LOG(LogLevel::WARNING) << "Connection already exist, fd: " << conn->GetFd();
            return;
        }

        // 注册事件至内核
        uint16_t events = conn->GetEvents(); // 获取关心事件
        int sockfd = conn->GetFd();          // 获取描述符

        _epoller_ptr->AddEvent(sockfd, events); // 注册事件

        // 注册conn至_connections哈希表
        _connections[sockfd] = conn;
    }

    ~TcpServer()
    {
    }

private:
    std::unique_ptr<Epoller> _epoller_ptr; // epoller类指针
    // std::shared_ptr<Listener> _listener_ptr; // listener类指针
    std::unordered_map<int, std::shared_ptr<Connection>> _connections; // fd -> connection, 描述每一个连接

    bool _isrunning; // 服务器是否运行

    struct epoll_event _revs[revs_num]; // 就绪事件数组
};
